// Rust 示例代码运行器
use std::env;
use std::fs;
use std::path::Path;
use std::process::Command;
use std::process;

// 引入 examples 模块
mod examples;
mod minigrep;
mod play;
mod hecto;

fn main() {
  let args: Vec<String> = env::args().collect();

  if args.len() < 2 {
    print_usage_and_examples();
    return;
  }

  let example_name = &args[1];

  match example_name.as_str() {
    "hecto" => hecto::run(),
    "play" => play::run(),
    "minigrep" => run_minigrep(),
    "list" => list_examples(),
    _ => run_example(example_name),
  }
}

fn run_minigrep() {
  let config = minigrep::Config::build(env::args()).unwrap_or_else(|err| {
    // 错误被写入到标准错误输出中，默认还是输出在控制台中。
    eprintln!("Problem parsing arguments: {err}");
    process::exit(1);
  });

    // 而成功的输出才会像下文例子样吐到 output.txt 中.
  // % cargo run > output.txt
  println!("Searching for {}", config.query);
  println!("In file {}", config.file_path);
  
  if let Err(e) = minigrep::run(config) {
    eprintln!("Application error: {e}");
    process::exit(1);
  }
}

fn print_usage_and_examples() {
  println!("Rust 学习示例运行器");
  println!("用法:");
  println!("  cargo run <示例名称>  - 运行指定的示例");
  println!("  cargo run list        - 列出所有可用的示例");
  println!("\n示例:");
  println!("  cargo run string      - 运行字符串示例");
  println!("  cargo run variables   - 运行变量和可变性示例");
  println!("  cargo run function    - 运行函数示例");
  println!("  cargo run ownership   - 运行所有权和借用示例");
  println!("  cargo run tuple       - 运行元组示例");
  println!("  cargo run array_vec   - 运行数组和向量示例");
  println!("  cargo run loops       - 运行循环示例");
  println!("  cargo run pattern_matching - 运行模式匹配示例");
  println!("  cargo run method      - 运行方法示例");
  println!("  cargo run trait_demo  - 运行特征示例");
  println!("  cargo run hash_map_demo - 运行HashMap示例");
  println!("  cargo run lifetime_demo - 运行生命周期示例");
}

fn list_examples() {
  println!("可用的示例:");

  let examples_dir = Path::new("src/examples");
  if !examples_dir.exists() {
    println!("错误: examples 目录不存在!");
    return;
  }

  match fs::read_dir(examples_dir) {
    Ok(entries) => {
      let mut found = false;

      for entry in entries {
        if let Ok(entry) = entry {
          let path = entry.path();
          if path.is_file()
            && path.extension().and_then(|s| s.to_str()) == Some("rs")
          {
            if let Some(stem) = path.file_stem().and_then(|s| s.to_str()) {
              println!("  - {}", stem);
              found = true;
            }
          }
        }
      }

      if !found {
        println!(
          "  没有找到示例文件。请在 src/examples/ 目录中创建 .rs 文件。"
        );
      }
    }
    Err(e) => {
      println!("无法读取示例目录: {}", e);
    }
  }
}

fn run_example(name: &str) {
  let example_path = format!("src/examples/{}.rs", name);
  let path = Path::new(&example_path);

  if !path.exists() {
    println!("错误: 示例 '{}' 不存在!", name);
    println!("请检查 src/examples 目录中是否有 {}.rs 文件", name);
    return;
  }

  println!("运行示例: {}\n", name);

  // 有两种方式运行示例:
  // 1. 直接调用示例的函数 (当已经加载到模块树中时更快)
  // 2. 编译并运行示例文件 (更通用，适用于任何新添加的示例)

  match name {
    "int_example" => {
      // 方式1: 直接调用模块中的函数
      examples::int_example::run_examples();
    }
    "float_example" => {
      // 方式1: 直接调用模块中的函数
      examples::float_example::run_examples();
    }
    "char_example" => {
      // 方式1: 直接调用模块中的函数
      examples::char_example::run_examples();
    }
    "fn_example" => {
      // 方式1: 直接调用模块中的函数
      examples::fn_example::run_examples();
    }
    "ownership_example" => {
      // 方式1: 直接调用模块中的函数
      examples::ownership_example::run_examples();
    }
    "string_example" => {
      // 方式1: 直接调用模块中的函数
      examples::string_example::run_examples();
    }
    "array_example" => {
      // 方式1: 直接调用模块中的函数
      examples::array_example::run_examples();
    }
    "tuple_example" => {
      // 方式1: 直接调用模块中的函数
      examples::tuple_example::run_examples();
    }
    "struct_example" => {
      // 方式1: 直接调用模块中的函数
      examples::struct_example::run_examples();
    }
    _ => {
      // 方式2: 编译并运行示例文件
      // 如果是新添加的示例但还没有在 mod.rs 中声明，则使用这种方式

      // 使用 rustc 编译并运行示例
      let output_path = format!("target/examples/{}", name);

      // 确保输出目录存在
      let _ = fs::create_dir_all("target/examples");

      // 编译示例文件
      let status = Command::new("rustc")
        .arg(&example_path)
        .arg("-o")
        .arg(&output_path)
        .status();

      match status {
        Ok(status) => {
          if status.success() {
            // 运行编译后的示例
            let run_status = Command::new(&output_path).status();

            match run_status {
              Ok(_) => {}
              Err(e) => println!("运行示例时出错: {}", e),
            }
          } else {
            println!("编译示例时出错!");
          }
        }
        Err(e) => println!("无法执行 rustc: {}", e),
      }
    }
  }
}
